# author@bupt_kt
# date@09/03/2021

# 测试集：Minst
# 正确率：0.8363
# 测试样例数：10000
##如果将样本的每个维度的取值二值化处理，可以简化问题，运算速度更快
import numpy as np
def input_data(y,dimension,value):
    data=[]
    file=open(r'Mnist/mnist_train.csv','r')
    for line in file.readlines():
        l=line.strip().split(',')
        data.append([int(num) for num in l[0:]])
    P=calculate(data,y,dimension,value)
    return P

##进行计算
def calculate(data,y,dimension,value):
    P=[]##所有情况的样例数都存在这个大数组中，P[y的取值][第几个维度][在该维度的取值]=满足对应条件的样例数目
    for i in range(y):
        P.append([])
        for j in range(dimension):
            P[i].append([])
            for k in range(value):
                P[i][j].append(0)

    for i in range(len(data)):
        P[data[i][0]][0][0]+=1 ##每个y值的个数
        for j in range(1,len(data[0])):
            P[data[i][0]][j][data[i][j]]+=1  ##条件概率下对应每种情况的个数


    return P

def test(P):
    data = []
    file = open(r'Mnist/mnist_test.csv', 'r')
    error=0
    for line in file.readlines():
        l = line.strip().split(',')
        data.append([int(num) for num in l[0:]])

    for i in range(len(data)):
        result=[]
        for y in range(len(P)):
            result.append(0)
            result[y]+=np.log((P[y][0][0]+1)/(60000+10))##这里用贝叶斯估计避免了出现0的情况，同时用log处理避免了小数相乘导致的结果下溢
            for j in range(1,len(data[i])):
                result[y]+=np.log((P[y][j][data[i][j]]+1)/(P[y][0][0]+256))
        predict=result.index(max(result))

        if predict!=data[i][0]:
            error+=1


    print(1-error/len(data))






if __name__ == '__main__':
    P=input_data(10,785,256)##三个参数分别表示：标记的种类，样例的维度（包括标记），每个维度的取值种数
    test(P)
